package com.woniuxy.ptapp.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniuxy.commons.util.BeanCopyUtil;
import com.woniuxy.commons.util.DateUtil;
import com.woniuxy.commons.util.Result;
import com.woniuxy.ptapp.common.exception.EnumExceptionCode;
import com.woniuxy.ptapp.common.exception.WoniuxyException;
import com.woniuxy.ptapp.common.param.LoginUser;
import com.woniuxy.ptapp.common.util.CheckCancelTime;
import com.woniuxy.ptapp.common.util.FinAccountIdByMessageId;
import com.woniuxy.ptapp.common.util.GetLogingUser;
import com.woniuxy.ptapp.common.util.OrderSequenceRandom;
import com.woniuxy.ptapp.common.xxljob.createJob.XxlJobCreateParam;
import com.woniuxy.ptapp.common.xxljob.createJob.XxlJobManager;
import com.woniuxy.ptapp.infra.ClassesOrderDao;
import com.woniuxy.ptapp.infra.model.ClassSchedule;
import com.woniuxy.ptapp.infra.model.ClassesInfo;
import com.woniuxy.ptapp.infra.model.ClassesOrder;
import com.woniuxy.ptapp.infra.model.ClassesOrderInfo;
import com.woniuxy.ptapp.service.ClassScheduleService;
import com.woniuxy.ptapp.service.ClassesInfoService;
import com.woniuxy.ptapp.service.ClassesOrderService;
import com.woniuxy.ptapp.service.dto.ByClassesDto;
import com.woniuxy.relation.client.AnnouncementClient;
import com.woniuxy.relation.client.form.SendAnnouncementForm;
import com.woniuxy.signing.client.CocahSigningVenueClient;
import com.woniuxy.signing.client.StudentSigningClient;
import com.woniuxy.signing.client.form.MakeSureSignForm;
import com.woniuxy.userapp.client.CoachClient;
import com.woniuxy.userapp.client.FrontAccountClient;
import com.woniuxy.userapp.client.StudentClient;
import com.woniuxy.userapp.client.VenueClient;
import com.woniuxy.userapp.client.param.AutoDeductMoneyInfo;
import com.woniuxy.userapp.client.param.CoachInfo;
import com.woniuxy.userapp.client.param.StudentInfo;
import com.woniuxy.userapp.client.param.VenueInfo;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 课程订单 服务实现类
 * </p>
 *
 * @author wangdong
 * @since 2022-07-30
 */
@Service
public class ClassesOrderServiceImpl extends ServiceImpl<ClassesOrderDao, ClassesOrder> implements ClassesOrderService {
    @Resource
    private GetLogingUser getLogingUser;
    @Resource
    private RocketMQTemplate rocketMQTemplate;
    @Resource
    private RedissonClient rc;
    @Resource
    private FrontAccountClient frontAccountClient;
    @Resource
    private VenueClient venueClient;
    @Resource
    private AnnouncementClient ac;
    @Resource
    private CoachClient coachClient;
    @Resource
    private StudentClient studentClient;
    @Resource
    private CocahSigningVenueClient cocahSigningVenueClient;
    @Resource
    private StudentSigningClient studentSigningClient;
    @Resource
    private XxlJobManager xxlJobCreator;
    @Resource
    private ClassesInfoService classesInfoService;
    @Resource
    private FinAccountIdByMessageId finaccountId;
    @Resource
    private XxlJobLogServiceImpl xxlJobLogService;
    @Resource
    private ClassScheduleService classScheduleService;
    //下单接口
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void Orders(ByClassesDto byClassesDto) {
        //生产锁对象
        RLock lock = rc.getLock("Orders:TakeOrder:1");
        try {
            //加锁
            lock.tryLock(10, 100, TimeUnit.SECONDS);
            //获取登录用户
            LoginUser logingUser = getLogingUser.getLogingUser();
            ClassSchedule classSchedule = classScheduleService.getOne(new QueryWrapper<ClassSchedule>().eq("id", byClassesDto.getClassScheduleId()));
            //通过课程表iD查询课程名称 并且判断课程id是否存在
            if (classSchedule == null) {
                throw new WoniuxyException(EnumExceptionCode.getClaessIdFail.getCode(), EnumExceptionCode.getClaessIdFail.getMessage());
            }
            ClassesInfo classesInfo = classesInfoService.getOne(new QueryWrapper<ClassesInfo>().eq("id", classSchedule.getClassesId()));

            //判断课程表时间是否重复
            if(classSchedule.getState()==1){
               throw new WoniuxyException(EnumExceptionCode.ThisCourseHasBeenReservation.getCode(),EnumExceptionCode.ThisCourseHasBeenReservation.getMessage() );
            }
            Result<BigDecimal> moneyByAccountId = frontAccountClient.findMoneyByAccountId(logingUser.getLoginId());
            if (moneyByAccountId == null || moneyByAccountId.getCode() != 200) {
                throw new WoniuxyException(EnumExceptionCode.FindMoneyByAccountIdFail.getCode(), EnumExceptionCode.FindMoneyByAccountIdFail
                        .getMessage());
            }
            //钱包里面的金额
            BigDecimal bigDecimal = moneyByAccountId.getData();
            if(bigDecimal==null){
                throw new WoniuxyException(EnumExceptionCode.LackOFBalance.getCode(),EnumExceptionCode.LackOFBalance.getMessage());
            }
            //需要判断该用户所有状态为已下单的订单之和的金额必须小于钱余额
            Result<StudentInfo> studentByAccountId = studentClient.findStudentByAccountId(logingUser.getLoginId());
            if (studentByAccountId == null || studentByAccountId.getCode() != 200 || studentByAccountId.getData().getId() == null) {
                throw new WoniuxyException(EnumExceptionCode.ThereIsNoStudent.getCode(), EnumExceptionCode.ThereIsNoStudent.getMessage());
            }
            QueryWrapper<ClassesOrder> queryWrapper = new QueryWrapper<ClassesOrder>();
            queryWrapper.eq("student_id", studentByAccountId.getData().getId());
            queryWrapper.eq("state", 12);

            List<ClassesOrder> classesOrderList = this.list(queryWrapper);
            BigDecimal bigDecimal1 = new BigDecimal(0);
            BigDecimal price = null;
            if (classesOrderList != null || classesOrderList.size() > 0) {
                for (ClassesOrder classesOrder : classesOrderList) {
                    bigDecimal1 = bigDecimal1.add(classesOrder.getPrice());
                }
            }
            if (bigDecimal1 == null) {
                price = classesInfo.getClassesPrice();
            } else {
                price = classesInfo.getClassesPrice().add(bigDecimal1);
            }
            int i = bigDecimal.compareTo(price);
            if (i < 0) {
                throw new WoniuxyException(EnumExceptionCode.LackOFBalance.getCode(), EnumExceptionCode.LackOFBalance.getMessage());
            }
            //判断下单的教练是否存在
            Result<Integer> accountIdByCoachId = coachClient.findAccountIdByCoachId(byClassesDto.getCoachId());
            if (accountIdByCoachId == null || accountIdByCoachId.getData() == null||accountIdByCoachId.getCode()!=200) {
                throw new WoniuxyException(EnumExceptionCode.ThereIsNoCoach.getCode(), EnumExceptionCode.ThereIsNoCoach.getMessage());
            }
            //判断下单的场馆是否存在
            Result<Integer> accountIdByVenueId1 = venueClient.findAccountIdByVenueId(byClassesDto.getVenueId());
            System.out.println(accountIdByVenueId1);
            if (accountIdByVenueId1 == null || accountIdByVenueId1.getData() == null|| accountIdByVenueId1.getCode()!=200) {
                throw new WoniuxyException(EnumExceptionCode.ThereIsNoVenue.getCode(), EnumExceptionCode.ThereIsNoVenue.getMessage());
            }
            //判断下单教练是否签约场馆
            MakeSureSignForm makeSureSignForm = new MakeSureSignForm();
            makeSureSignForm.setCocahId(byClassesDto.getCoachId() + "");
            makeSureSignForm.setVenueId(byClassesDto.getVenueId() + "");
            Result result = cocahSigningVenueClient.makeSureSign(makeSureSignForm);
            if (result == null || result.getCode() != 200) {
                throw new WoniuxyException(EnumExceptionCode.CoachVenueNoContractRelationship.getCode(), EnumExceptionCode.CoachVenueNoContractRelationship.getMessage());
            }
            //判断该学员是否第一次下该教练的课程,添加教练和学员签约关系
            QueryWrapper<ClassesOrder> queryWrapper2 = new QueryWrapper<ClassesOrder>();
            queryWrapper2.eq("student_id", studentByAccountId.getData().getId());
            queryWrapper2.eq("coach_id", byClassesDto.getCoachId());
            List<ClassesOrder> list = this.list(queryWrapper2);
            if (list == null || list.size() <= 0) {
                Result result1 = studentSigningClient.studentSigningCocah(byClassesDto.getCoachId() + "", studentByAccountId.getData().getId() + "");
                if (result1 == null || result1.getCode() != 200) {
                    throw new WoniuxyException(EnumExceptionCode.CoachStudentsSigningRelationshipFailure.getCode(), EnumExceptionCode.CoachStudentsSigningRelationshipFailure.getMessage());
                }
            }
            //通过教练Id查询教练信息
            Result<CoachInfo> coach = coachClient.findCoachByCoachId(byClassesDto.getCoachId());
            if (coach == null || coach.getCode() != 200) {
                throw new WoniuxyException(EnumExceptionCode.findCoachMessageFail.getCode(), EnumExceptionCode.findCoachMessageFail.getMessage());
            }
            //通过场馆id查询场馆信息
            Result<VenueInfo> venue = venueClient.findVenueByVenueId(byClassesDto.getVenueId());
            if (venue == null || venue.getCode() != 200) {
                throw new WoniuxyException(EnumExceptionCode.findVenueMessageFail.getCode(), EnumExceptionCode.findVenueMessageFail.getMessage());
            }
            ClassesOrder classesOrder = BeanCopyUtil.copyObject(byClassesDto, ClassesOrder.class);
            classesOrder.setClassesId(classSchedule.getClassesId());
            classesOrder.setClassTime(classSchedule.getClassesStartTime());
            classesOrder.setClassesName(classSchedule.getClassesName());
            classesOrder.setVenueName(venue.getData().getVenueName());
            classesOrder.setCoachName(coach.getData().getName());
            classesOrder.setStudentId(studentByAccountId.getData().getId());
            classesOrder.setStudentName(logingUser.getLoginName());
            classesOrder.setOrderDate(DateUtil.timeFormatString(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss"));
            classesOrder.setPrice(classesInfo.getClassesPrice());
            //生成订单编号
            String orderSnRandom = OrderSequenceRandom.createOrderSnRandom();
            classesOrder.setOrderNum(orderSnRandom);
            //保存下单信息
            boolean save = this.save(classesOrder);
            if (!save) {
                throw new WoniuxyException(EnumExceptionCode.byClassesOrderFail.getCode(), EnumExceptionCode.byClassesOrderFail.getMessage());
            }
            //修改课程表状态
            classSchedule.setState(1);
            boolean b = classScheduleService.saveOrUpdate(classSchedule);
            if(!b){
               throw new WoniuxyException(EnumExceptionCode.ModifyTheCurriculumStatusfailed.getCode(),EnumExceptionCode.ModifyTheCurriculumStatusfailed.getMessage() );
            }
            //发送消息队列下单1个小时未接单取消订单
            Message<Integer> message1 = MessageBuilder.withPayload(classesOrder.getId()).
                    setHeader("KEYS", UUID.randomUUID()).build();
            rocketMQTemplate.syncSend("Orders:takeOrders", message1, 3000, 16);
            //预约之后需要向场馆发送预约订单信息通知
            //通过场馆id查询账号id
            Result<Integer> accountIdByVenueId = venueClient.findAccountIdByVenueId(byClassesDto.getVenueId());
            if (accountIdByVenueId == null || accountIdByVenueId.getData() == null) {
                throw new WoniuxyException(EnumExceptionCode.ThereIsNoVenue.getCode(), EnumExceptionCode.ThereIsNoVenue.getMessage());
            }
            SendAnnouncementForm sendAnnouncementForm = new SendAnnouncementForm();
            Integer venueid = accountIdByVenueId.getData();
            sendAnnouncementForm.setAcceptAccountId(venueid + "");
            sendAnnouncementForm.setContent("尊敬的" + venue.getData().getVenueName() + "您有一笔新的订单预约,请及时查看接单");
            ac.sendAnnouncement(sendAnnouncementForm);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    //查询登录用户的所有订单
    @Override
    public List<ClassesOrderInfo> showClassesOrder() {
        //获取登录人的信息
        LoginUser logingUser = getLogingUser.getLogingUser();
        //判断登录人的角色
        List<ClassesOrder> classesOrders = null;
        if (logingUser.getLoginRole() == 1) {
            //查询场馆的订单
            Result<VenueInfo> venueByAccountId = venueClient.findVenueByAccountId(logingUser.getLoginId());
            if (venueByAccountId == null || venueByAccountId.getCode() != 200) {
                throw new WoniuxyException(EnumExceptionCode.ThereIsNoVenue.getCode(), EnumExceptionCode.ThereIsNoVenue.getMessage());
            }
            classesOrders = this.list(new QueryWrapper<ClassesOrder>().eq("venue_id", venueByAccountId.getData().getId()));
        } else if (logingUser.getLoginRole() == 2) {
            //查询教练的订单
            Result<CoachInfo> coachByAccountId = coachClient.findCoachByAccountId(logingUser.getLoginId());
            if (coachByAccountId == null || coachByAccountId.getCode() != 200) {
                throw new WoniuxyException(EnumExceptionCode.ThereIsNoCoach.getCode(), EnumExceptionCode.ThereIsNoCoach.getMessage());
            }
            classesOrders = this.list(new QueryWrapper<ClassesOrder>().eq("coach_id", coachByAccountId.getData().getId()));
        } else if (logingUser.getLoginRole() == 3) {
            //查询学员的订单
            Result<StudentInfo> studentByAccountId = studentClient.findStudentByAccountId(logingUser.getLoginId());
            if (studentByAccountId == null || studentByAccountId.getCode() != 200) {
                throw new WoniuxyException(EnumExceptionCode.ThereIsNoStudent.getCode(), EnumExceptionCode.ThereIsNoStudent.getMessage());
            }
            classesOrders = this.list(new QueryWrapper<ClassesOrder>().eq("student_id", studentByAccountId.getData().getId()));
        }
        if (null == classesOrders) {
            throw new WoniuxyException(EnumExceptionCode.NoHaveClassesOrder.getCode(), EnumExceptionCode.NoHaveClassesOrder.getMessage());
        }
        List<ClassesOrderInfo> classesOrderDtos = BeanCopyUtil.copyList(classesOrders, ClassesOrderInfo.class);
        return classesOrderDtos;
    }

    //接单
    @Override
    public void takeOrder(Integer id) {
        //获取登录人的信息
        LoginUser logingUser = getLogingUser.getLogingUser();
        ClassesOrder classesOrder = this.getOne(new QueryWrapper<ClassesOrder>().eq("id", id));
        if (null == classesOrder) {
            throw new WoniuxyException(EnumExceptionCode.getClassesOrderFail.getCode(), EnumExceptionCode.getClassesOrderFail.getMessage());
        }
        //判断是否超时接单
        if (classesOrder.getState() == 5) {
            throw new WoniuxyException(EnumExceptionCode.timeoutTakeOrders.getCode(), EnumExceptionCode.timeoutTakeOrders.getMessage());
        }
        //场馆接单
        if (logingUser.getLoginRole() == 1) {
            //判断该订单id是否是该场馆的
            Result<VenueInfo> venueByAccountId = venueClient.findVenueByAccountId(logingUser.getLoginId());
            if (venueByAccountId == null || venueByAccountId.getCode() != 200) {
                throw new WoniuxyException(EnumExceptionCode.ThereIsNoVenue.getCode(), EnumExceptionCode.ThereIsNoVenue
                        .getMessage());
            }
            QueryWrapper<ClassesOrder> classesOrderQueryWrapper = new QueryWrapper<ClassesOrder>();
            classesOrderQueryWrapper.eq("id", id);
            classesOrderQueryWrapper.eq("venue_id", venueByAccountId.getData().getId());
            ClassesOrder classesOrder1 = this.getOne(classesOrderQueryWrapper);
            if (null == classesOrder1) {
                throw new WoniuxyException(EnumExceptionCode.OrderDoesNotBelongToTheVenues.getCode(), EnumExceptionCode.OrderDoesNotBelongToTheVenues
                        .getMessage());
            }
            //场馆接单 订单状态只能为已下单才可以接单
            if (classesOrder1.getState() != 12) {
                throw new WoniuxyException(EnumExceptionCode.VenueDontAnswerOrders.getCode(), EnumExceptionCode.VenueDontAnswerOrders.getMessage());
            }
            //修改订单状态为场馆接单
            classesOrder1.setState(2);
            //录入场馆操作时间
            classesOrder1.setVenueReceiveDate(DateUtil.timeFormatString(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss"));
            //保存
            boolean b = this.saveOrUpdate(classesOrder1);
            if (!b) {
                throw new WoniuxyException(EnumExceptionCode.ChangeOrederStateFail.getCode(), EnumExceptionCode.ChangeOrederStateFail
                        .getMessage());
            }
            //通知教练接单
            Result<Integer> accountIdByCoachId = coachClient.findAccountIdByCoachId(classesOrder.getCoachId());
            if (accountIdByCoachId == null || accountIdByCoachId.getData() == null) {
                throw new WoniuxyException(EnumExceptionCode.ThereIsNoCoach.getCode(), EnumExceptionCode.ThereIsNoCoach.getMessage());
            }
            SendAnnouncementForm saf = new SendAnnouncementForm();
            saf.setAcceptAccountId(accountIdByCoachId.getData() + "");
            saf.setContent("教练员:" + classesOrder.getCoachName() + "您好,您有一次新的预约,您的场馆已经接单，请您尽快接单,祝您生活愉快");
            ac.sendAnnouncement(saf);
        } else if (logingUser.getLoginRole() == 2) {
            //判断该订单是否属于该教练
            Result<CoachInfo> coachByAccountId = coachClient.findCoachByAccountId(logingUser.getLoginId());
            if (coachByAccountId == null || coachByAccountId.getCode() != 200 || coachByAccountId.getData().getId() == null) {
                throw new WoniuxyException(EnumExceptionCode.ThereIsNoCoach.getCode(), EnumExceptionCode.ThereIsNoCoach.getMessage());
            }

            QueryWrapper<ClassesOrder> classesOrderQueryWrapper = new QueryWrapper<ClassesOrder>();
            classesOrderQueryWrapper.eq("id", id);
            classesOrderQueryWrapper.eq("coach_id", coachByAccountId.getData().getId());
            ClassesOrder one = this.getOne(classesOrderQueryWrapper);
            if (null == one) {
                throw new WoniuxyException(EnumExceptionCode.OrderDoesNotBelongToTheCoach.getCode(), EnumExceptionCode.OrderDoesNotBelongToTheCoach
                        .getMessage());
            }
            //判断教练是否可以接单（教练只能在场馆接单的状态才可以接单）
            if (one.getState() != 2) {
                throw new WoniuxyException(EnumExceptionCode.VenueDontAnswerOrders.getCode(), EnumExceptionCode.VenueDontAnswerOrders.getMessage());
            }
            //教练点击接单修改订单状态为待上课（教练接单了就代表待上课状态）
            one.setState(3);
            //录入教练操作时间
            one.setCoachReceiveDate(DateUtil.timeFormatString(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss"));
            boolean b = this.saveOrUpdate(one);
            if (!b) {
                throw new WoniuxyException(EnumExceptionCode.ChangeOrederStateFail.getCode(), EnumExceptionCode.ChangeOrederStateFail
                        .getMessage());
            }
            //发送通知给学员预约成功（系统发送）
            Result<Integer> accountIdByStudentId = studentClient.findAccountIdByStudentId(classesOrder.getStudentId());
            if (accountIdByStudentId == null || accountIdByStudentId.getData() == null) {
                throw new WoniuxyException(EnumExceptionCode.ThereIsNoStudent.getCode(), EnumExceptionCode.ThereIsNoStudent.ThereIsNoCoach.getMessage());
            }
            SendAnnouncementForm saf = new SendAnnouncementForm();
            saf.setAcceptAccountId(accountIdByStudentId.getData() + "");
            saf.setContent("尊敬的会员:" + classesOrder.getStudentName() + "您好,您预约的" + classesOrder.getCoachName() + "教练员已预约成功,上课时间" + classesOrder.getClassTime() + "感谢您的支持！祝您生活愉快");
            ac.sendAnnouncement(saf);
        }
    }

    /**
     * @param id           订单表id
     * @param refuseReason 拒绝理由
     */
    @GlobalTransactional(rollbackFor = Exception.class)
    @Override
    public void rejectionOrders(Integer id, String refuseReason) {
        //获取登录人的信息
        LoginUser logingUser = getLogingUser.getLogingUser();

        ClassesOrder classesOrder = this.getOne(new QueryWrapper<ClassesOrder>().eq("id", id));

        if (null == classesOrder) {
            throw new WoniuxyException(EnumExceptionCode.getClassesOrderFail.getCode(), EnumExceptionCode.getClassesOrderFail.getMessage());
        }

        //判断是否超时接单，如果超时则不需要拒单
        if (classesOrder.getState() == 5) {
            throw new WoniuxyException(EnumExceptionCode.timeoutTakeOrders.getCode(), EnumExceptionCode.timeoutTakeOrders.getMessage());
        }
        //判断登录人角色
        if (logingUser.getLoginRole() == 1) {
            //判断该订单id是否是该场馆的
            Result<VenueInfo> venueByAccountId = venueClient.findVenueByAccountId(logingUser.getLoginId());
            if (venueByAccountId == null || venueByAccountId.getData().getId() == null || venueByAccountId.getCode() == 500) {
                throw new WoniuxyException(EnumExceptionCode.ThereIsNoVenue.getCode(), EnumExceptionCode.ThereIsNoVenue
                        .getMessage());
            }
            QueryWrapper<ClassesOrder> classesOrderQueryWrapper = new QueryWrapper<ClassesOrder>();
            classesOrderQueryWrapper.eq("id", id);
            classesOrderQueryWrapper.eq("venue_id", venueByAccountId.getData().getId());
            ClassesOrder classesOrder1 = this.getOne(classesOrderQueryWrapper);
            if (null == classesOrder1) {
                throw new WoniuxyException(EnumExceptionCode.OrderDoesNotBelongToTheVenues.getCode(), EnumExceptionCode.OrderDoesNotBelongToTheVenues
                        .getMessage());
            }
            //只有在订单状态已下单的时候才场馆才可以拒单，教练无需拒单
            if (classesOrder1.getState() != 12) {
                throw new WoniuxyException(EnumExceptionCode.DontRefusedOrders.getCode(), EnumExceptionCode.DontRefusedOrders.getMessage());
            }
            //修改订单状态为场馆拒单
            classesOrder1.setState(7);
            classesOrder1.setVenueRefuseReason(refuseReason);
            //录入场馆操作时间
            classesOrder1.setVenueReceiveDate(DateUtil.timeFormatString(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss"));
            //保存
            boolean b = this.saveOrUpdate(classesOrder1);
            if (!b) {
                throw new WoniuxyException(EnumExceptionCode.ChangeOrederStateFail.getCode(), EnumExceptionCode.ChangeOrederStateFail.getMessage());
            }
            //发送通知给用户
            Result<Integer> accountIdByStudentId = studentClient.findAccountIdByStudentId(classesOrder1.getStudentId());
            if (accountIdByStudentId == null || accountIdByStudentId.getData() == null) {
                throw new WoniuxyException(EnumExceptionCode.ThereIsNoStudent.getCode(), EnumExceptionCode.ThereIsNoStudent.ThereIsNoCoach.getMessage());
            }
            SendAnnouncementForm saf = new SendAnnouncementForm();
            saf.setAcceptAccountId(accountIdByStudentId.getData() + "");
            saf.setContent("尊敬的" + classesOrder.getStudentName() + "您好,由于场馆" + refuseReason + "原因,已经拒绝了您的预约，非常抱歉给您带来不便,详细情况您可以联系一下场馆");
            ac.sendAnnouncement(saf);
        } else if (logingUser.getLoginRole() == 2) {

            Result<CoachInfo> coachByAccountId = coachClient.findCoachByAccountId(logingUser.getLoginId());
            if (coachByAccountId == null || coachByAccountId.getCode() != 200 || coachByAccountId.getData().getId() == null) {
                throw new WoniuxyException(EnumExceptionCode.ThereIsNoCoach.getCode(), EnumExceptionCode.ThereIsNoCoach.getMessage());
            }

            QueryWrapper<ClassesOrder> classesOrderQueryWrapper = new QueryWrapper<ClassesOrder>();
            classesOrderQueryWrapper.eq("id", id);
            classesOrderQueryWrapper.eq("coach_id", coachByAccountId.getData().getId());
            ClassesOrder one = this.getOne(classesOrderQueryWrapper);
            if (null == one) {
                throw new WoniuxyException(EnumExceptionCode.OrderDoesNotBelongToTheCoach.getCode(), EnumExceptionCode.OrderDoesNotBelongToTheCoach
                        .getMessage());
            }
            //判断教练是否可以拒单（教练只能在场馆接单的状态才可以拒单）
            if (one.getState() != 2) {
                throw new WoniuxyException(EnumExceptionCode.DontRefusedOrders.getCode(), EnumExceptionCode.DontRefusedOrders.getMessage());
            }
            //教练点击接单修改订单状态为教练拒单
            one.setState(8);
            //录入教练操作时间
            one.setCoachReceiveDate(DateUtil.timeFormatString(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss"));
            one.setCoachRefuseReason(refuseReason);
            //保存
            boolean b = this.saveOrUpdate(one);
            if (!b) {
                throw new WoniuxyException(EnumExceptionCode.ChangeOrederStateFail.getCode(), EnumExceptionCode.ChangeOrederStateFail.getMessage());
            }
            //发送通知给用户
            //场馆账号id
            Result<Integer> accountIdByVenueId = venueClient.findAccountIdByVenueId(one.getVenueId());
            //学员账号id
            Result<Integer> accountIdByStudentId = studentClient.findAccountIdByStudentId(one.getStudentId());
            if (accountIdByStudentId == null || accountIdByStudentId.getData() == null) {
                throw new WoniuxyException(EnumExceptionCode.ThereIsNoStudent.getCode(), EnumExceptionCode.ThereIsNoStudent.ThereIsNoCoach.getMessage());
            }
            SendAnnouncementForm saf = new SendAnnouncementForm();
            saf.setAcceptAccountId(accountIdByStudentId.getData() + "");
            saf.setContent("尊敬的" + classesOrder.getStudentName() + "您好,由于教练" + refuseReason + "原因,已经拒绝了您的预约，非常抱歉给您带来不便,详细情况您可以联系一下场馆");
            ac.sendAnnouncement(saf);
            if (accountIdByVenueId == null || accountIdByVenueId.getData() == null) {
                throw new WoniuxyException(EnumExceptionCode.ThereIsNoVenue.getCode(), EnumExceptionCode.ThereIsNoVenue.getMessage());
            }
            //发送通知给场馆
            SendAnnouncementForm saff = new SendAnnouncementForm();
            saff.setAcceptAccountId(accountIdByVenueId.getData() + "");
            saff.setContent("领导您好,我是" + logingUser.getLoginName() + "教练员,由于" + refuseReason + "原因,我已经拒绝了学员的预约,请知晓");
            ac.sendAnnouncement(saff);
        }

    }

    //教练确认上课完成
    @Override
    public void finishClassesOreder(Integer id) {
        LoginUser logingUser = getLogingUser.getLogingUser();
        //判断改订单是否属于该教练
        Result<CoachInfo> coachByAccountId = coachClient.findCoachByAccountId(logingUser.getLoginId());
        if (coachByAccountId == null || coachByAccountId.getCode() != 200 || coachByAccountId.getData().getId() == null) {
            throw new WoniuxyException(EnumExceptionCode.ThereIsNoCoach.getCode(), EnumExceptionCode.ThereIsNoCoach.getMessage());
        }
        QueryWrapper<ClassesOrder> classesOrderQueryWrapper = new QueryWrapper<ClassesOrder>();
        classesOrderQueryWrapper.eq("id", id);
        classesOrderQueryWrapper.eq("coach_id", coachByAccountId.getData().getId());
        ClassesOrder one = this.getOne(classesOrderQueryWrapper);

        if (null == one) {
            throw new WoniuxyException(EnumExceptionCode.TheOrderNotBelongToThisCoach.getCode(), EnumExceptionCode.TheOrderNotBelongToThisCoach.getMessage());
        }
        //教练只能在订单状态为待上课才可以点击完成
        if (one.getState() != 3) {
            throw new WoniuxyException(EnumExceptionCode.TheStateCantClickFinish.getCode(), EnumExceptionCode.TheStateCantClickFinish.getMessage());
        }
        one.setState(4);
        one.setClassesEndtime(DateUtil.timeFormatString(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss"));
        boolean b = saveOrUpdate(one);
        if (!b) {
            throw new WoniuxyException(EnumExceptionCode.ChangeOrederStateFail.getCode(), EnumExceptionCode.ChangeOrederStateFail.getMessage());
        }
        Result<Integer> accountIdByStudentId = studentClient.findAccountIdByStudentId(one.getStudentId());
        if (accountIdByStudentId == null || accountIdByStudentId.getData() == null) {
            throw new WoniuxyException(EnumExceptionCode.ThereIsNoStudent.getCode(), EnumExceptionCode.ThereIsNoStudent.getMessage());
        }
        SendAnnouncementForm sendAnnouncementForm = new SendAnnouncementForm();
        sendAnnouncementForm.setContent("尊敬的会员"+one.getStudentName()+"您的课程"+one.getClassesName()+"已经结束,请您尽快支付课程费用,感谢您的支持和理解,祝您生活愉快");
        sendAnnouncementForm.setAcceptAccountId(accountIdByStudentId.getData()+"");
        ac.sendAnnouncement(sendAnnouncementForm);
        //如果学员半个小时未支付,将学员钱包的钱自动支付给教练
        XxlJobCreateParam param = new XxlJobCreateParam();
        param.setExecutorId(4);
        param.setJobDesc("超时未支付");
        param.setScheduleConf(dateToCron(LocalDateTime.now().plusMinutes(30)));
        param.setExecutorHandler("UnpaidOvertime");
        Integer venueAccountId = finaccountId.findVenueAccountId(one.getVenueId());
        String str = venueAccountId + "," + one.getPrice() + "," + accountIdByStudentId.getData() + "," + one.getId();
        param.setExecutorParam(str);
        int job = xxlJobCreator.createJob(param);

    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void studentCancelOrder(Integer id) {
        LoginUser logingUser = getLogingUser.getLogingUser();
        //判断该订单id是否属于登录用户
        Result<StudentInfo> studentByAccountId = studentClient.findStudentByAccountId(logingUser.getLoginId());
        if (studentByAccountId == null || studentByAccountId.getCode() != 200 || studentByAccountId.getData().getId() == null) {
            throw new WoniuxyException(EnumExceptionCode.ThereIsNoStudent.getCode(), EnumExceptionCode.ThereIsNoStudent.getMessage());
        }
        QueryWrapper<ClassesOrder> queryWrapper = new QueryWrapper<ClassesOrder>();
        queryWrapper.eq("id", id);
        ClassesOrder classesOrder = this.getOne(queryWrapper);
        if (null == classesOrder) {
            throw new WoniuxyException(EnumExceptionCode.getClassesOrderFail.getCode(), EnumExceptionCode.getClassesOrderFail.getMessage());
        }
        //判断如果订单已经被场馆，教练拒单,订单超时未接单取消，学员已经取消订单，已付款,订单已完成
        if (classesOrder.getState() == 7 || classesOrder.getState() == 8 || classesOrder.getState() == 5 || classesOrder.getState() == 13 || classesOrder.getState() == 1 ||
                classesOrder.getState() == 4 || classesOrder.getState() == 9 || classesOrder.getState() == 10) {
            throw new WoniuxyException(EnumExceptionCode.TheStateCantCancelTheOrder.getCode(), EnumExceptionCode.TheStateCantCancelTheOrder.getMessage());
        }
        //上课时间
        String classTime = classesOrder.getClassTime();
        //当前时间
        long l = System.currentTimeMillis();
        String nowTime = DateUtil.timeFormatString(l, "yyyy-MM-dd HH:mm:ss");
        //判断取消订单的时间是否大于开课前30分钟
        Boolean check = CheckCancelTime.Check(classTime, nowTime);
        if (!check) {
            //取消订单时间低于30分钟需要支付违约金给场馆
            BigDecimal price = classesOrder.getPrice();
            double v = price.doubleValue();
            double dedit = v * 0.1;
            Result<Integer> accountIdByVenueId = venueClient.findAccountIdByVenueId(classesOrder.getVenueId());
            if (accountIdByVenueId == null || accountIdByVenueId.getData() == null) {
                throw new WoniuxyException(EnumExceptionCode.ThereIsNoVenue.getCode(), EnumExceptionCode.ThereIsNoVenue.getMessage());
            }
            BigDecimal bigDecimal = BigDecimal.valueOf(dedit);
            AutoDeductMoneyInfo autoDeductMoneyInfo = new AutoDeductMoneyInfo();
            autoDeductMoneyInfo.setDeductionId(logingUser.getLoginId());
            autoDeductMoneyInfo.setMoneyAmount(bigDecimal);
            autoDeductMoneyInfo.setAddId(accountIdByVenueId.getData());
            Result result = frontAccountClient.autoDeductMoney(autoDeductMoneyInfo);
            if (result == null || result.getCode() != 200) {
                throw new WoniuxyException(EnumExceptionCode.PenaltyDeductionsFailure.getCode(), EnumExceptionCode.PenaltyDeductionsFailure.getMessage());
            }
            classesOrder.setIsBreach(1);
            classesOrder.setPenalty(bigDecimal);
            classesOrder.setPenaltyReason("用户取消时间低30分钟");
            classesOrder.setPenaltyMan(logingUser.getLoginName());
        }
        //修改订单状态
        classesOrder.setState(13);
        classesOrder.setCancelDate(DateUtil.timeFormatString(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss"));
        boolean b = this.saveOrUpdate(classesOrder);
        if (!b) {
            throw new WoniuxyException(EnumExceptionCode.ChangeOrederStateFail.getCode(), EnumExceptionCode.ChangeOrederStateFail
                    .getMessage());
        }
        //查询场馆的账号id
        Result<Integer> accountIdByVenueId = venueClient.findAccountIdByVenueId(classesOrder.getVenueId());
        if (accountIdByVenueId == null || accountIdByVenueId.getData() == null) {
            throw new WoniuxyException(EnumExceptionCode.ThereIsNoVenue.getCode(), EnumExceptionCode.ThereIsNoVenue.getMessage());
        }
        //用户取消订单系统给场馆发送通知
        SendAnnouncementForm saff = new SendAnnouncementForm();
        saff.setAcceptAccountId(accountIdByVenueId.getData() + "");
        saff.setContent(classesOrder.getVenueName() + "您好,由于学员:" + logingUser.getLoginName() + "申请了取消订单,目前已经取消成功,如果有异议请联系学员,请知晓");
        Result result = ac.sendAnnouncement(saff);
        //系统给教练发送通知
        Result<Integer> accountIdByCoachId = coachClient.findAccountIdByCoachId(classesOrder.getCoachId());
        if (accountIdByCoachId == null || accountIdByCoachId.getData() == null) {
            throw new WoniuxyException(EnumExceptionCode.ThereIsNoCoach.getCode(), EnumExceptionCode.ThereIsNoCoach.getMessage());
        }
        SendAnnouncementForm saff1 = new SendAnnouncementForm();
        saff1.setAcceptAccountId(accountIdByCoachId.getData() + "");
        saff1.setContent(classesOrder.getCoachName() + "教练,您好,由于学员:" + logingUser.getLoginName() + "申请了取消订单,目前已经取消成功,如果有异议请联系学员,请知晓");
        Result result1 = ac.sendAnnouncement(saff1);
        if (result == null || result.getCode() != 200 || result1 == null || result1.getCode() != 200) {
            throw new WoniuxyException(EnumExceptionCode.SendANotificationFailure.getCode(), EnumExceptionCode.SendANotificationFailure.getMessage());
        }
    }

    public String dateToCron(LocalDateTime date) {
        String cronFormat = "ss mm HH dd MM ? yyyy";
        return DateTimeFormatter.ofPattern(cronFormat).format(date);
    }
}

